github.com/jbking/gohan@v0.0.0-20151217002006-b41ccf1c2a96/extension/otto/gohan_resource_management.go (about) 1 // Copyright (C) 2015 NTT Innovation Institute, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 // implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 package otto 17 18 import ( 19 "github.com/dop251/otto" 20 21 "github.com/cloudwan/gohan/extension" 22 "github.com/cloudwan/gohan/schema" 23 "github.com/cloudwan/gohan/server/resources" 24 ) 25 26 const ( 27 noEnvironmentForSchemaErrorMessageFormat = "No environment for schema '%s'" 28 wrongResponseErrorMessageFormat = "Wrong response from %s" 29 notADictionaryErrorMessageFormat = "Not a dictionary: '%v'" 30 ) 31 32 func handleChainError(env *Environment, call *otto.FunctionCall, err error) { 33 switch err := err.(type) { 34 default: 35 ThrowOttoException(call, err.Error()) 36 case resources.ResourceError: 37 throwOtto(call, "ResourceException", err.Message, err.Problem) 38 case extension.Error: 39 exceptionInfo, _ := env.VM.ToValue(err.ExceptionInfo) 40 throwOtto(call, "ExtensionException", err.Error(), exceptionInfo) 41 } 42 } 43 44 func init() { 45 gohanChainingInit := func(env *Environment) { 46 vm := env.VM 47 builtins := map[string]interface{}{ 48 "gohan_model_list": func(call otto.FunctionCall) otto.Value { 49 VerifyCallArguments(&call, "gohan_model_list", 3) 50 rawContext, _ := call.Argument(0).Export() 51 context, ok := rawContext.(map[string]interface{}) 52 if !ok { 53 ThrowOttoException(&call, noContextMessage) 54 } 55 schemaID := call.Argument(1).String() 56 manager := schema.GetManager() 57 currentSchema, ok := manager.Schema(schemaID) 58 if !ok { 59 ThrowOttoException(&call, unknownSchemaErrorMesssageFormat, schemaID) 60 } 61 context["schema"] = currentSchema 62 context["path"] = currentSchema.GetPluralURL() 63 filterObj, _ := call.Argument(2).Export() 64 filter := map[string]interface{}{} 65 if filterObj != nil { 66 filterMap := filterObj.(map[string]interface{}) 67 for key, value := range filterMap { 68 switch value := value.(type) { 69 default: 70 ThrowOttoException(&call, "Filter not a string nor array of strings") 71 case string: 72 filter[key] = value 73 case []interface{}: 74 for _, val := range value { 75 v, ok := val.(string) 76 if !ok { 77 ThrowOttoException(&call, "Filter not a string nor array of strings") 78 } 79 filter[key] = v 80 } 81 } 82 } 83 } 84 if err := resources.GetResourcesInTransaction( 85 context, currentSchema, filter, nil); err != nil { 86 handleChainError(env, &call, err) 87 } 88 response, ok := context["response"].(map[string]interface{}) 89 if !ok { 90 ThrowOttoException(&call, "No response") 91 } 92 resources, ok := response[currentSchema.Plural] 93 if !ok { 94 ThrowOttoException(&call, wrongResponseErrorMessageFormat, "GetMultipleResources.") 95 } 96 value, _ := vm.ToValue(resources) 97 return value 98 }, 99 "gohan_model_fetch": func(call otto.FunctionCall) otto.Value { 100 VerifyCallArguments(&call, "gohan_model_fetch", 4) 101 rawContext, _ := call.Argument(0).Export() 102 context, ok := rawContext.(map[string]interface{}) 103 if !ok { 104 ThrowOttoException(&call, noContextMessage) 105 } 106 schemaID := call.Argument(1).String() 107 manager := schema.GetManager() 108 currentSchema, ok := manager.Schema(schemaID) 109 if !ok { 110 ThrowOttoException(&call, unknownSchemaErrorMesssageFormat, schemaID) 111 } 112 context["schema"] = currentSchema 113 context["path"] = currentSchema.GetPluralURL() 114 resourceID := call.Argument(2).String() 115 rawTenantIDs, _ := call.Argument(3).Export() 116 tenantIDs, ok := rawTenantIDs.([]string) 117 if !ok { 118 tenantIDs = nil 119 } 120 if err := resources.GetSingleResourceInTransaction( 121 context, currentSchema, resourceID, tenantIDs); err != nil { 122 handleChainError(env, &call, err) 123 } 124 response, ok := context["response"].(map[string]interface{}) 125 if !ok { 126 ThrowOttoException(&call, "No response") 127 } 128 resource := response[currentSchema.Singular] 129 value, _ := vm.ToValue(resource) 130 return value 131 }, 132 "gohan_model_create": func(call otto.FunctionCall) otto.Value { 133 VerifyCallArguments(&call, "gohan_model_create", 3) 134 rawContext, _ := call.Argument(0).Export() 135 context, ok := rawContext.(map[string]interface{}) 136 if !ok { 137 ThrowOttoException(&call, noContextMessage) 138 } 139 schemaID := call.Argument(1).String() 140 manager := schema.GetManager() 141 currentSchema, ok := manager.Schema(schemaID) 142 if !ok { 143 ThrowOttoException(&call, unknownSchemaErrorMesssageFormat, schemaID) 144 } 145 context["schema"] = currentSchema 146 context["path"] = currentSchema.GetPluralURL() 147 data, _ := call.Argument(2).Export() 148 dataMap, ok := data.(map[string]interface{}) 149 if !ok { 150 ThrowOttoException(&call, notADictionaryErrorMessageFormat, dataMap) 151 } 152 resourceObj, err := manager.LoadResource(currentSchema.ID, dataMap) 153 if err != nil { 154 handleChainError(env, &call, err) 155 } 156 if err := resources.CreateResourceInTransaction( 157 context, resourceObj); err != nil { 158 handleChainError(env, &call, err) 159 } 160 response, ok := context["response"].(map[string]interface{}) 161 if !ok { 162 ThrowOttoException(&call, "No response") 163 } 164 resource := response[currentSchema.Singular] 165 value, _ := vm.ToValue(resource) 166 return value 167 }, 168 "gohan_model_update": func(call otto.FunctionCall) otto.Value { 169 VerifyCallArguments(&call, "gohan_model_update", 5) 170 rawContext, _ := call.Argument(0).Export() 171 context, ok := rawContext.(map[string]interface{}) 172 if !ok { 173 ThrowOttoException(&call, noContextMessage) 174 } 175 schemaID := call.Argument(1).String() 176 manager := schema.GetManager() 177 currentSchema, ok := manager.Schema(schemaID) 178 if !ok { 179 ThrowOttoException(&call, unknownSchemaErrorMesssageFormat, schemaID) 180 } 181 context["schema"] = currentSchema 182 context["path"] = currentSchema.GetPluralURL() 183 resourceID := call.Argument(2).String() 184 data, _ := call.Argument(3).Export() 185 186 rawTenantIDs, _ := call.Argument(4).Export() 187 tenantIDs, ok := rawTenantIDs.([]string) 188 if !ok { 189 tenantIDs = nil 190 } 191 192 dataMap, ok := data.(map[string]interface{}) 193 if !ok { 194 ThrowOttoException(&call, notADictionaryErrorMessageFormat, dataMap) 195 } 196 err := resources.UpdateResourceInTransaction(context, currentSchema, resourceID, dataMap, tenantIDs) 197 if err != nil { 198 handleChainError(env, &call, err) 199 } 200 response, ok := context["response"].(map[string]interface{}) 201 if !ok { 202 ThrowOttoException(&call, "No response") 203 } 204 resource := response[currentSchema.Singular] 205 value, _ := vm.ToValue(resource) 206 return value 207 }, 208 "gohan_model_delete": func(call otto.FunctionCall) otto.Value { 209 VerifyCallArguments(&call, "gohan_model_delete", 3) 210 rawContext, _ := call.Argument(0).Export() 211 context, ok := rawContext.(map[string]interface{}) 212 if !ok { 213 ThrowOttoException(&call, noContextMessage) 214 } 215 schemaID := call.Argument(1).String() 216 manager := schema.GetManager() 217 currentSchema, ok := manager.Schema(schemaID) 218 if !ok { 219 ThrowOttoException(&call, unknownSchemaErrorMesssageFormat, schemaID) 220 } 221 context["schema"] = currentSchema 222 context["path"] = currentSchema.GetPluralURL() 223 resourceID := call.Argument(2).String() 224 err := resources.DeleteResourceInTransaction(context, currentSchema, resourceID) 225 if err != nil { 226 handleChainError(env, &call, err) 227 } 228 return otto.Value{} 229 }, 230 } 231 232 for name, object := range builtins { 233 vm.Set(name, object) 234 } 235 } 236 RegisterInit(gohanChainingInit) 237 }