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 }