func (ccm *ContractChaincodeMetadata) CompileSchemas() error {
	compileSchema := func(propName string, schema *spec.Schema, components ComponentMetadata) (*gojsonschema.Schema, error) {
		combined := make(map[string]interface{})
		combined["components"] = components
		combined["properties"] = make(map[string]interface{})
		combined["properties"].(map[string]interface{})[propName] = schema
		combinedLoader := gojsonschema.NewGoLoader(combined)
		return gojsonschema.NewSchema(combinedLoader)
	}
	for contractName, contract := range ccm.Contracts {
		for txIdx, tx := range contract.Transactions {
			for paramIdx, param := range tx.Parameters {
				gjsSchema, err := compileSchema(param.Name, param.Schema, ccm.Components)
				if err != nil {
					return fmt.Errorf("Error compiling schema for %s [%s]. %s schema invalid. %s", contractName, tx.Name, param.Name, err.Error())
				}
				param.CompiledSchema = gjsSchema
				tx.Parameters[paramIdx] = param
			}
			if tx.Returns.Schema != nil {
				gjsSchema, err := compileSchema("return", tx.Returns.Schema, ccm.Components)
				if err != nil {
					return fmt.Errorf("Error compiling schema for %s [%s]. Return schema invalid. %s", contractName, tx.Name, err.Error())
				}
				tx.Returns.CompiledSchema = gjsSchema
			}
			contract.Transactions[txIdx] = tx
		}
		ccm.Contracts[contractName] = contract
	}
	return nil
}
CompileSchemas compile parameter and return schemas for use by gojsonschema.
When validating against the compiled schema you will need to make the
comparison json have a key of the parameter name for parameters or
return for return values e.g {"param1": "value"}. Compilation process
resolves references to components
package metadata
import (
	"encoding/json"
	"errors"
	"fmt"
	os "os"
	"path/filepath"
	"reflect"
	"github.com/go-openapi/spec"
	"github.com/gobuffalo/packr"
	"github.com/hyperledger/fabric-contract-api-go/internal/utils"
	"github.com/xeipuuv/gojsonschema"
)
const MetadataFolder = "META-INF"
const MetadataFolderSecondary = "contract-metadata"
const MetadataFile = "metadata.json"
type osInterface interface {
	Executable() (string, error)
	Stat(string) (os.FileInfo, error)
	IsNotExist(error) bool
}
type osFront struct{}
func (o osFront) Executable() (string, error) {
	return os.Executable()
}
func (o osFront) Stat(name string) (os.FileInfo, error) {
	return os.Stat(name)
}
func (o osFront) IsNotExist(err error) bool {
	return os.IsNotExist(err)
}
var osAbs osInterface = osFront{}
func GetJSONSchema() ([]byte, error) {
	box := packr.NewBox("./schema")
	schema, err := box.Find("schema.json")
	return schema, err
}
type ParameterMetadata struct {
	Description    string               `json:"description,omitempty"`
	Name           string               `json:"name"`
	Schema         *spec.Schema         `json:"schema"`
	CompiledSchema *gojsonschema.Schema `json:"-"`
}
type ReturnMetadata struct {
	Schema         *spec.Schema
	CompiledSchema *gojsonschema.Schema
}
type TransactionMetadata struct {
	Parameters []ParameterMetadata `json:"parameters,omitempty"`
	Returns    ReturnMetadata      `json:"-"`
	Tag        []string            `json:"tag,omitempty"`
	Name       string              `json:"name"`
}
type tmAlias TransactionMetadata
type jsonTransactionMetadata struct {
	*tmAlias
	ReturnsSchema *spec.Schema `json:"returns,omitempty"`
}
func (tm *TransactionMetadata) UnmarshalJSON(data []byte) error {
	jtm := jsonTransactionMetadata{tmAlias: (*tmAlias)(tm)}
	err := json.Unmarshal(data, &jtm)
	if err != nil {
		return err
	}
	tm.Returns = ReturnMetadata{}
	tm.Returns.Schema = jtm.ReturnsSchema
	return nil
}
func (tm *TransactionMetadata) MarshalJSON() ([]byte, error) {
	jtm := jsonTransactionMetadata{tmAlias: (*tmAlias)(tm), ReturnsSchema: tm.Returns.Schema}
	return json.Marshal(&jtm)
}
type ContactMetadata struct {
	Name  string `json:"name,omitempty"`
	URL   string `json:"url,omitempty"`
	Email string `json:"email,omitempty"`
}
type LicenseMetadata struct {
	Name string `json:"name,omitempty"`
	URL  string `json:"url,omitempty"`
}
type InfoMetadata struct {
	Description string           `json:"description,omitempty"`
	Title       string           `json:"title,omitempty"`
	Contact     *ContactMetadata `json:"contact,omitempty"`
	License     *LicenseMetadata `json:"license,omitempty"`
	Version     string           `json:"version,omitempty"`
}
type ContractMetadata struct {
	Info         *InfoMetadata         `json:"info,omitempty"`
	Name         string                `json:"name"`
	Transactions []TransactionMetadata `json:"transactions"`
	Default      bool                  `json:"default"`
}
type ObjectMetadata struct {
	ID                   string                 `json:"$id"`
	Properties           map[string]spec.Schema `json:"properties"`
	Required             []string               `json:"required"`
	AdditionalProperties bool                   `json:"additionalProperties"`
}
type ComponentMetadata struct {
	Schemas map[string]ObjectMetadata `json:"schemas,omitempty"`
}
type ContractChaincodeMetadata struct {
	Info       *InfoMetadata               `json:"info,omitempty"`
	Contracts  map[string]ContractMetadata `json:"contracts"`
	Components ComponentMetadata           `json:"components"`
}
func (ccm *ContractChaincodeMetadata) Append(source ContractChaincodeMetadata) {
	if ccm.Info == nil {
		ccm.Info = source.Info
	}
	if len(ccm.Contracts) == 0 {
		if ccm.Contracts == nil {
			ccm.Contracts = make(map[string]ContractMetadata)
		}
		for key, value := range source.Contracts {
			ccm.Contracts[key] = value
		}
	}
	if reflect.DeepEqual(ccm.Components, ComponentMetadata{}) {
		ccm.Components = source.Components
	}
}