github.com/bhameyie/otto@v0.2.1-0.20160406174117-16052efa52ec/helper/compile/customization.go (about)

     1  package compile
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/hashicorp/otto/appfile"
     7  	"github.com/hashicorp/otto/helper/schema"
     8  )
     9  
    10  // CustomizationFunc is the callback called for customizations.
    11  type CustomizationFunc func(*schema.FieldData) error
    12  
    13  // Customization is used to configure how customizations are processed.
    14  type Customization struct {
    15  	// Schema is the actual schema of the customization configuration. This
    16  	// will be type validated automatically.
    17  	Schema map[string]*schema.FieldSchema
    18  
    19  	// Callback is the callback that is called to process this customization.
    20  	// This is guaranteed to be called even if there is no customization set
    21  	// to allow you to setup defaults.
    22  	Callback CustomizationFunc
    23  }
    24  
    25  // Merge will merge this customization with the other and return a new
    26  // customization. The original customization is not modified.
    27  func (c *Customization) Merge(other *Customization) *Customization {
    28  	result := &Customization{
    29  		Schema: make(map[string]*schema.FieldSchema),
    30  	}
    31  
    32  	// Merge the schemas
    33  	for k, v := range c.Schema {
    34  		result.Schema[k] = v
    35  	}
    36  	for k, v := range other.Schema {
    37  		result.Schema[k] = v
    38  	}
    39  
    40  	// Wrap the callbacks
    41  	result.Callback = func(d *schema.FieldData) error {
    42  		if err := c.Callback(d); err != nil {
    43  			return err
    44  		}
    45  
    46  		return other.Callback(d)
    47  	}
    48  
    49  	return result
    50  }
    51  
    52  func processCustomizations(cs *appfile.CustomizationSet, c *Customization) error {
    53  	// If we have no customization we do nothing
    54  	if c == nil {
    55  		return nil
    56  	}
    57  
    58  	// We process customizations below by going through multiple
    59  	// passes. We can very likely condense this into one for loop but
    60  	// it helps the semantic understanding to split it out and there should
    61  	// never be so many customizations where the optimizations here matter.
    62  
    63  	// We start by going through, building the FieldData.
    64  	rawData := make(map[string]interface{})
    65  
    66  	// Go through all the customizations and merge. We only do
    67  	// key-level merging.
    68  	if cs != nil {
    69  		for _, c := range cs.Raw {
    70  			for k, v := range c.Config {
    71  				rawData[k] = v
    72  			}
    73  		}
    74  	}
    75  
    76  	// Build the FieldData structure from it
    77  	data := &schema.FieldData{
    78  		Raw:    rawData,
    79  		Schema: c.Schema,
    80  	}
    81  
    82  	// Validate it. If it is valid, then we're fine.
    83  	if err := data.Validate(); err != nil {
    84  		return fmt.Errorf("Error in customization: %s", err)
    85  	}
    86  
    87  	// Call the callback
    88  	if err := c.Callback(data); err != nil {
    89  		return fmt.Errorf("Error in customization: %s", err)
    90  	}
    91  
    92  	return nil
    93  }